﻿using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using System;
using System.Collections.Generic;

namespace JsonFastBenchmark
{
    [SimpleJob(RuntimeMoniker.Net461)]
    [SimpleJob(RuntimeMoniker.Net60)]
    [SimpleJob(RuntimeMoniker.Net70)] 
    [MemoryDiagnoser]
    public class BenchmarkComplex
    {
        public const int Count = 100;

        [Benchmark(Baseline = true)]
        public void DirectNew_ComplexObject()
        {
            var v =GetComplexObject();
            for (int i = 0; i < Count; i++)
            {
                byte[] bytes = new byte[80*1024];//开辟小内存模拟序列化
                var val = GetComplexObject();//直接新建，模拟反序列化
            }
        }

        [Benchmark]
        public void NewtonsoftJson_ComplexObject()
        {
            var v = GetComplexObject();
            for (int i = 0; i < Count; i++)
            {
                var str = Newtonsoft.Json.JsonConvert.SerializeObject(v);
                var val = Newtonsoft.Json.JsonConvert.DeserializeObject<ComplexObject>(str);
            }
        }

        [Benchmark]
        public void JsonFast_ComplexObject()
        {
            var v = GetComplexObject();
            for (int i = 0; i < Count; i++)
            {
                var str = JsonFast.JsonFastConverter.JsonTo(v);
                var val = JsonFast.JsonFastConverter.JsonFrom<ComplexObject>(str);
            }
        }
        
        [Benchmark]
        public void TouchSocketJson_ComplexObject()
        {
            var v = GetComplexObject();
            for (int i = 0; i < Count; i++)
            {
                var str = TouchSocket.Core.Serialization.JsonWriter.ToJson(v);
                var val = TouchSocket.Core.Serialization.JsonParser.FromJson<ComplexObject>(str);
            }
        }

        private ComplexObject GetComplexObject()
        {
            ComplexObject complexObject = new ComplexObject();
            complexObject.P1 = 10;
            complexObject.P2 = "天下无敌";
            complexObject.P3 = 100;
            complexObject.P4 = 0;
            complexObject.P5 = DateTime.Now;
            complexObject.P6 = 10;
            complexObject.P7 = new byte[1024 * 64];

            Random random = new Random();
            random.NextBytes(complexObject.P7);

            complexObject.List1 = new List<int>();
            complexObject.List1.Add(1);
            complexObject.List1.Add(2);
            complexObject.List1.Add(3);

            complexObject.List2 = new List<string>();
            complexObject.List2.Add("1");
            complexObject.List2.Add("2");
            complexObject.List2.Add("3");

            complexObject.List3 = new List<byte[]>();
            complexObject.List3.Add(new byte[1024]);
            complexObject.List3.Add(new byte[1024]);
            complexObject.List3.Add(new byte[1024]);

            complexObject.Dic1 = new Dictionary<int, int>();
            complexObject.Dic1.Add(1, 1);
            complexObject.Dic1.Add(2, 2);
            complexObject.Dic1.Add(3, 3);

            complexObject.Dic2 = new Dictionary<int, string>();
            complexObject.Dic2.Add(1, "1");
            complexObject.Dic2.Add(2, "2");
            complexObject.Dic2.Add(3, "3");

            complexObject.Dic3 = new Dictionary<string, string>();
            complexObject.Dic3.Add("1", "1");
            complexObject.Dic3.Add("2", "2");
            complexObject.Dic3.Add("3", "3");

            complexObject.Dic4 = new Dictionary<int, Arg>();
            complexObject.Dic4.Add(1, new Arg(1));
            complexObject.Dic4.Add(2, new Arg(2));
            complexObject.Dic4.Add(3, new Arg(3));
            return complexObject;
        }
    }

    public class ComplexObject
    {
        public Dictionary<int, int> Dic1 { get; set; }
        public Dictionary<int, string> Dic2 { get; set; }
        public Dictionary<string, string> Dic3 { get; set; }
        public Dictionary<int, Arg> Dic4 { get; set; }
        public List<int> List1 { get; set; }
        public List<string> List2 { get; set; }
        public List<byte[]> List3 { get; set; }
        public int P1 { get; set; }
        public string P2 { get; set; }
        public long P3 { get; set; }
        public byte P4 { get; set; }
        public DateTime P5 { get; set; }
        public double P6 { get; set; }
        public byte[] P7 { get; set; }
    }

    public class Arg
    {
        public Arg()
        {
        }

        public Arg(int myProperty)
        {
            MyProperty = myProperty;
        }

        public int MyProperty { get; set; }
    }
}
